﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace SCG.WinForms
{
    public partial class Spin : UserControl
    {
        //events
        public event EventHandler<EventArgs> ValueChanged;
        public event EventHandler<EventArgs> MaxValueRequested;

        //constructor
        public Spin()
        {
            InitializeComponent();
        }

        //value
        public int Value
        {
            get
            {
                return Int32.Parse(lblValue.Text);
            }
            set
            {
                if (value < MinValue)
                    value = MinValue;
                if (value > MaxValue)
                    value = MaxValue;
                if (Value != value)
                {
                    lblValue.Text = value.ToString();
                    if (ValueChanged != null)
                        ValueChanged(this, EventArgs.Empty);
                }
            }
        }

        //arrow color
        public Color ArrowColor { get; set; }

        //min/max
        private int _minValue = 0;
        public int MinValue
        {
            get
            {
                return _minValue;
            }
            set
            {
                _minValue = value;
                if (Value < _minValue)
                    Value = _minValue;
            }
        }
        private int _maxValue = 100;
        public int MaxValue
        {
            get
            {
                return _maxValue;
            }
            set
            {
                _maxValue = value;
                if (Value > _maxValue)
                    Value = _maxValue;
            }
        }

        //set width of label
        private void Spin_Resize(object sender, EventArgs e)
        {
            lblValue.Width = Width - btnMaxLeft.Width - btnMaxRight.Width;
        }

        //right arrow
        private void btnRight_MouseDown(object sender, MouseEventArgs e)
        {
            Value++;
            lblValue.Refresh();
            _stop = false;
            _increment = 1;
            _delay = 500;
            Thread spinThread = new Thread(Increment);
            spinThread.Start();
        }
        private void btnRight_MouseUp(object sender, MouseEventArgs e)
        {
            _stop = true;
        }

        //left arrow
        private void btnLeft_MouseDown(object sender, MouseEventArgs e)
        {
            Value--;
            lblValue.Refresh();
            _stop = false;
            _increment = -1;
            _delay = 500;
            Thread spinThread = new Thread(Increment);
            spinThread.Start();
        }
        private void btnLeft_MouseUp(object sender, MouseEventArgs e)
        {
            _stop = true;
        }

        //handle it
        private void Increment()
        {
            while (!_stop)
            {
                Thread.Sleep(_delay);
                _delay = (int)(_delay * 0.7);
                if (_delay < 10)
                    _delay = 10;
                if (_stop)
                    return;
                Invoke((MethodInvoker)delegate
                {
                    Value += _increment;
                    lblValue.Refresh();
                });
            }
        }

        //private members
        private bool _stop;
        private int _increment;
        private int _delay;

        //set to min value
        private void btnMaxLeft_Click(object sender, EventArgs e)
        {
            Value = MinValue;
            lblValue.Refresh();
        }

        //request max value
        private void btnMaxRight_Click(object sender, EventArgs e)
        {
            if (MaxValueRequested != null)
                MaxValueRequested(this, EventArgs.Empty);
            else
                Value = MaxValue;
            lblValue.Refresh();
        }

        //render max right arrow
        private void btnMaxRight_Paint(object sender, PaintEventArgs e)
        {
            Point[] pts = new Point[3];
            pts[0] = new Point(4, 4);
            pts[1] = new Point(btnMaxRight.Width - 4, btnMaxRight.Height / 2);
            pts[2] = new Point(4, btnMaxRight.Height - 4);
            e.Graphics.FillPolygon(new SolidBrush(ArrowColor), pts);
        }

        //render right button
        private void btnRight_Paint(object sender, PaintEventArgs e)
        {
            Point[] pts = new Point[3];
            pts[0] = new Point(4, 4);
            pts[1] = new Point(btnRight.Width - 4, btnRight.Height / 2);
            pts[2] = new Point(4, btnRight.Height - 4);
            e.Graphics.DrawPolygon(new Pen(ArrowColor), pts);
        }

        //render left button
        private void btnLeft_Paint(object sender, PaintEventArgs e)
        {
            Point[] pts = new Point[3];
            pts[0] = new Point(btnLeft.Width - 4, 4);
            pts[1] = new Point(4, btnLeft.Height / 2);
            pts[2] = new Point(btnLeft.Width - 4, btnLeft.Height - 4);
            e.Graphics.DrawPolygon(new Pen(ArrowColor), pts);
        }

        //render max left button
        private void btnMaxLeft_Paint(object sender, PaintEventArgs e)
        {
            Point[] pts = new Point[3];
            pts[0] = new Point(btnMaxLeft.Width - 4, 4);
            pts[1] = new Point(4, btnMaxLeft.Height / 2);
            pts[2] = new Point(btnMaxLeft.Width - 4, btnMaxLeft.Height - 4);
            e.Graphics.FillPolygon(new SolidBrush(ArrowColor), pts);
        }
    }
}
